<!--
 * @Author: wcx 1055127249@qq.com
 * @Date: 2024-12-30 11:32:47
 * @LastEditors: wcx 1055127249@qq.com
 * @LastEditTime: 2025-01-21 15:31:36
 * @FilePath: \my-project\src\views\CreateFormBiz\index.vue
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
-->
<template>
  <MainContainer>
    <!-- 表单设计区域 -->
    <draggable v-model="fieldsArray" v-bind="dragFormProps" class="form-design" @change="log">
      <draggableItem v-for="(element, i) in fieldsArray" v-bind="{ element, formConfig, active: fieldsIndex === i }" :key="i"  @click="setIndex(i)"/>
    </draggable>
    <!-- 表单项列表 -->
    <div slot="left">
      <div class="list-group-title">表单项列表</div>
      <draggable class="list-group" v-bind="itemListProps">
        <div class="list-item" v-for="(item, i) in formItemList" :key="i">{{ item.label }}</div>
      </draggable>
    </div>
    <!-- 表单配置 -->
    <div slot="right">
      <div class="config-header">
        <span :class="activeName === 'from' ? 'active' : ''" @click="activeName = 'from'">表单</span>
        <span :class="activeName === 'fromItem' ? 'active' : ''" @click="activeName = 'fromItem'">表单项</span>
      </div>
      <div class="config-body" v-if="activeName === 'from'">
        <field label="标签宽度" v-model="formConfig.labelWidth" />
        <field label="表单尺寸" v-model="formConfig.size" type="select" :options="fieldOptions" />
        <field label="表单尺寸" v-model="formConfig.labelPosition" type="select" :options="['right', 'left', 'top']" />
        <field label="单行模式" v-model="formConfig.displayInner" type="switch" />
        <field label="是否显示校验错误信息" v-model="formConfig.showMessage" type="switch" />
        <field label="是否在输入框中显示校验结果反馈图标" v-model="formConfig.statusIcon" type="switch" />
      </div>
      <div class="config-body" v-if="activeName === 'fromItem'">
        <field label="标签" v-model="formItem.label" />
        <field label="参数" v-model="formItem.parameter" v-if="formItem.type !== 'el-button'"/>
        <field label="是否必填" v-model="formItem.required" type="switch" />
        <field label="宽度" v-model="formItem.width" type="slider" :format-tooltip="v=>v+'%'" :step="2" :min="20"/>
          {{typeof formItem.width}}
        <field label="选项" v-if="['el-select', 'el-radio-group', 'el-checkbox-group'].includes(formItem.type)">
          <el-switch slot="right" v-model="isAsyncOption">动态</el-switch>
          <InputTable v-if="!isAsyncOption" v-model="formItem.options" :columns="['label', 'value']"/>
          <div v-else>
            function (http) {
            <el-input v-model="formItem.asyncOption" type="textarea" rows="3" placeholder="return http.get('/api/dict')"/>
            }
          </div>
        </field>
        <field label="按钮列表" v-if="formItem.type === 'buttons'">
          <InputTable v-model="formItem.list" :columns="['label', {name: 'type', type: 'el-select', options: ['primary', 'success', 'info', 'warning', 'danger']}]"/>
        </field>
        <field label="动态校验">
          function (http) {
          <el-input v-model="formItem.asyncOption" type="textarea" rows="3" placeholder="return http.get('/api/dict')"/>
          }
        </field>
        <field label="动态显示">
          function (http) {
          <el-input v-model="formItem.show" type="textarea" rows="3" placeholder="return http.get('/api/dict')"/>
          }
        </field>
      </div>
    </div>
    <!-- 顶部工具栏 -->
    <div slot="header" class="header-bar">
      <div class="left-tools">
        <el-button size="small" type="primary" @click="showForm">预览</el-button>
        <el-button size="small" type="primary">导入</el-button>
      </div>
    </div>
    <Preview ref="preview" />
  </MainContainer>
</template>

<script>
import draggable from 'vuedraggable'
import MainContainer from './components/container.vue'
import Field from './components/configField.vue'
import Preview from './components/preview.vue'
import draggableItem from './components/draggableItem.vue'
import InputTable from './components/InputTable'
import InputArray from './components/InputArray'
import InputObject from './components/InputObject'
import { generateRandomString } from '@/utils'
import formItem from '@/utils/formUtils'
export default {
  components: {
    draggable,
    'el-object': InputObject,
    'el-objectArray': InputArray,
    MainContainer,
    draggableItem,
    InputTable,
    Preview,
    Field,
  },
  data() {
    const list = formItem.map((i, id) => ({id, key: i.is || i.value, label: i.label, props: i.props}))
    return {
      fieldsIndex: 0,
      fieldsArray: [],
      activeName: 'from',
      isAsyncOption: false,
      formConfig: {
        displayInner: true,
        size: 'small',
        labelWidth: '100px',
      },
      fieldOptions: ['small', 'medium', 'large'],
      formItemList: [
        ...list,
        { key: 'el-object', label: '对象' },
        { key: 'el-objectArray', label: '数组对象' },
        { key: 'el-button', label: '按钮' }
      ]
    }
  },
  computed: {
    itemListProps() {
      return {
        sort: false,
        group: {
          put: false,
          pull: 'clone',
          name: 'people',
        },
        list: this.formItemList,
        clone: this.cloneFormItem
      }
    },
    dragFormProps() {
      return {
        tag: 'el-form',
        group: 'people',
        animation: 200,
        disabled: false,
        ghostClass: 'ghost',
        componentData: {
          attrs: this.formConfig,
        }
      }
    },
    formItem() {
      if (this.fieldsArray[this.fieldsIndex]) {
        return this.fieldsArray[this.fieldsIndex]
      }
      return {}
    },
  },
  methods: {
    showForm() {
      console.log(this.fieldsArray)
      this.$refs.preview.show(this.fieldsArray, this.formConfig)
    },
    log({ added, removed, moved }) {
      if (added) {
        this.fieldsIndex = added.newIndex
      } else if (removed) {
        this.fieldsIndex = 0
      } else if (moved) {
        this.fieldsIndex = moved.newIndex
      }
      this.activeName = 'fromItem'
    },
    setIndex(i){
      this.fieldsIndex = i
    },
    cloneFormItem({ key, label, props }) {
      const itemData = {
        label,
        props,
        type: key,
        width: 100,
        parameter: key.replace('el-', '') + '-' + generateRandomString(10),
      }
      if (key === 'el-button') {
        itemData.label = ''
        itemData.type = 'buttons'
        itemData.props = undefined
        itemData.list = [{ label: '按钮文字' }]
      } else if (['el-select', 'el-radio-group', 'el-checkbox-group'].includes(key)) {
        itemData.options = [
          { label: '选项1', value: '1' },
          { label: '选项2', value: '2' },
          { label: '选项3', value: '3' },
        ]
      }
      return itemData
    },
    scrollToError() {
      const err = this.$refs.form.$el.querySelector('.el-form-item__error');
      if (err) err.scrollIntoView({ block: 'center', behavior: 'smooth' });
    }
  },
}
</script>

<style lang="scss" scoped>
.form-design {
  min-height: 50vh;
}

.list-group {
  display: flex;
  flex-wrap: wrap;
  padding-top: 20px;
  padding-left: 20px;
}

.list-group-title {
  height: 50px;
  border-bottom: 1px solid #EBEEF5;
  line-height: 50px;
  font-size: 14px;
  color: #000;
  padding: 0 20px;
  font-weight: bold;
}

.list-item {
  width: 100px;
  border: 1px solid #EBEEF5;
  margin-right: 10px;
  margin-bottom: 10px;
  font-size: 14px;
  line-height: 30px;
  padding: 0 10px;
}

.header-bar {
  display: flex;
  align-items: center;
  margin-top: 11px;
}

.config-header {
  display: flex;
  align-items: center;
  border-bottom: 1px solid #EBEEF5;
  line-height: 50px;
  font-size: 14px;
  color: #000;
  padding: 0 20px;
  font-weight: bold;

  span {
    display: block;
    margin-right: 20px;
    cursor: pointer;
  }

  .active {
    color: #409eff;
  }
}

.config-body {
  padding: 20px;
}
</style>